Add TAL-Reverb-II plugin to test
[juce-lv2.git] / juce / source / extras / browser plugins / wrapper / juce_ActiveX_GlueCode.cpp
blobd1ba634480946b511d1295abf15bd9cc5ea4db1d
1 /*
2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-11 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 //==============================================================================
28 This file contains all the gubbins to create an ActiveX browser plugin that
29 wraps your BrowserPluginComponent object.
32 //==============================================================================
33 #if _MSC_VER
35 //==============================================================================
36 #include <windows.h>
37 #include <windowsx.h>
38 #include <olectl.h>
39 #include <objsafe.h>
40 #include <exdisp.h>
41 #pragma warning (disable:4584)
43 #include "juce_IncludeBrowserPluginInfo.h"
44 #include "../../../juce_amalgamated.h"
45 #include "juce_BrowserPluginComponent.h"
47 #ifndef JuceBrowserPlugin_ActiveXCLSID
48 #error "For an activeX plugin, you need to define JuceBrowserPlugin_ActiveXCLSID in your BrowserPluginCharacteristics.h file!"
49 #endif
51 //==============================================================================
52 #if JUCE_DEBUG
53 static int numDOWID = 0, numJuceSO = 0;
54 #endif
56 #define log(a) DBG(a)
58 // Cunning trick used to add functions to export list without messing about with .def files.
59 #define EXPORTED_FUNCTION comment(linker, "/EXPORT:" __FUNCTION__ "=" __FUNCDNAME__)
61 //==============================================================================
62 static void juceVarToVariant (const var& v, VARIANT& dest);
63 static const var variantTojuceVar (const VARIANT& v);
65 //==============================================================================
66 // Takes care of the logic in invoking var methods from IDispatch callbacks.
67 class IDispatchHelper
69 public:
70 IDispatchHelper() {}
71 ~IDispatchHelper() {}
73 const String getStringFromDISPID (const DISPID hash) const
75 for (int i = identifierPool.size(); --i >= 0;)
76 if (getHashFromString (identifierPool[i]) == hash)
77 return identifierPool[i];
79 return String::empty;
82 HRESULT doGetIDsOfNames (LPOLESTR* rgszNames, UINT cNames, DISPID* rgDispId)
84 for (unsigned int i = 0; i < cNames; ++i)
85 rgDispId[i] = getHashFromString (identifierPool.getPooledString (String (rgszNames[i])));
87 return S_OK;
90 HRESULT doInvoke (const var& v,
91 DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
92 VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
94 const Identifier memberId (getStringFromDISPID (dispIdMember));
96 DynamicObject* const object = v.getDynamicObject();
98 if (memberId.toString().isEmpty() || object == nullptr)
99 return DISP_E_MEMBERNOTFOUND;
101 if ((wFlags & DISPATCH_METHOD) != 0)
103 if (! object->hasMethod (memberId))
104 return DISP_E_MEMBERNOTFOUND;
106 const int numArgs = pDispParams == nullptr ? 0 : pDispParams->cArgs;
107 var result;
109 if (numArgs == 0)
111 result = v.call (memberId);
113 else
115 Array<var> args;
116 for (int j = numArgs; --j >= 0;)
117 args.add (variantTojuceVar (pDispParams->rgvarg[j]));
119 result = v.invoke (memberId, numArgs == 0 ? 0 : args.getRawDataPointer(), numArgs);
122 if (pVarResult != nullptr)
123 juceVarToVariant (result, *pVarResult);
125 return S_OK;
127 else if ((wFlags & DISPATCH_PROPERTYGET) != 0)
129 if (! object->hasProperty (memberId))
130 return DISP_E_MEMBERNOTFOUND;
132 if (pVarResult != nullptr)
134 juceVarToVariant (object->getProperty (memberId), *pVarResult);
135 return S_OK;
138 else if ((wFlags & DISPATCH_PROPERTYPUT) != 0)
140 if (pDispParams != nullptr && pDispParams->cArgs > 0)
142 object->setProperty (memberId, variantTojuceVar (pDispParams->rgvarg[0]));
143 return S_OK;
147 return DISP_E_MEMBERNOTFOUND;
150 private:
151 StringPool identifierPool;
153 static DISPID getHashFromString (const String::CharPointerType& s) noexcept
155 return (DISPID) (pointer_sized_int) s.getAddress();
158 IDispatchHelper (const IDispatchHelper&);
159 IDispatchHelper& operator= (const IDispatchHelper&);
162 //==============================================================================
163 // Makes a var look like an IDispatch
164 class IDispatchWrappingDynamicObject : public IDispatch
166 public:
167 IDispatchWrappingDynamicObject (const var& object_)
168 : object (object_),
169 refCount (1)
171 DBG ("num Juce wrapper objs: " + String (++numJuceSO));
174 virtual ~IDispatchWrappingDynamicObject()
176 DBG ("num Juce wrapper objs: " + String (--numJuceSO));
179 HRESULT __stdcall QueryInterface (REFIID id, void __RPC_FAR* __RPC_FAR* result)
181 if (id == IID_IUnknown) { AddRef(); *result = (IUnknown*) this; return S_OK; }
182 else if (id == IID_IDispatch) { AddRef(); *result = (IDispatch*) this; return S_OK; }
184 *result = 0;
185 return E_NOINTERFACE;
188 ULONG __stdcall AddRef() { return ++refCount; }
189 ULONG __stdcall Release() { const int r = --refCount; if (r == 0) delete this; return r; }
191 HRESULT __stdcall GetTypeInfoCount (UINT*) { return E_NOTIMPL; }
192 HRESULT __stdcall GetTypeInfo (UINT, LCID, ITypeInfo**) { return E_NOTIMPL; }
194 HRESULT __stdcall GetIDsOfNames (REFIID riid, LPOLESTR* rgszNames, UINT cNames,
195 LCID lcid, DISPID* rgDispId)
197 return iDispatchHelper.doGetIDsOfNames (rgszNames, cNames, rgDispId);
200 HRESULT __stdcall Invoke (DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
201 DISPPARAMS* pDispParams, VARIANT* pVarResult,
202 EXCEPINFO* pExcepInfo, UINT* puArgErr)
204 return iDispatchHelper.doInvoke (object, dispIdMember, riid, lcid, wFlags, pDispParams,
205 pVarResult, pExcepInfo, puArgErr);
208 private:
209 //==============================================================================
210 var object;
211 int refCount;
212 IDispatchHelper iDispatchHelper;
216 //==============================================================================
217 // Makes an IDispatch look like a var
218 class DynamicObjectWrappingIDispatch : public DynamicObject
220 IDispatch* const source;
222 public:
223 DynamicObjectWrappingIDispatch (IDispatch* const source_)
224 : source (source_)
226 source->AddRef();
227 log ("num IDispatch wrapper objs: " + String (++numDOWID));
230 ~DynamicObjectWrappingIDispatch()
232 source->Release();
233 log ("num IDispatch wrapper objs: " + String (--numDOWID));
236 var getProperty (const Identifier& propertyName) const
238 const String nameCopy (propertyName.toString());
239 LPCOLESTR name = nameCopy.toUTF16();
240 DISPID id = 0;
241 if (source->GetIDsOfNames (IID_NULL, (LPOLESTR*) &name, 1, 0, &id) == S_OK)
243 EXCEPINFO excepInfo;
244 DISPPARAMS params;
245 zerostruct (params);
246 UINT argError;
247 VARIANT result;
248 zerostruct (result);
250 if (source->Invoke (id, IID_NULL, 0, DISPATCH_PROPERTYGET,
251 &params, &result, &excepInfo, &argError) == S_OK)
253 var v (variantTojuceVar (result));
254 VariantClear (&result);
255 return v;
259 return var::null;
262 bool hasProperty (const Identifier& propertyName) const
264 const String nameCopy (propertyName.toString());
265 LPCOLESTR name = nameCopy.toUTF16();
266 DISPID id = 0;
267 return source->GetIDsOfNames (IID_NULL, (LPOLESTR*) &name, 1, 0, &id) == S_OK;
270 void setProperty (const Identifier& propertyName, const var& newValue)
272 const String nameCopy (propertyName.toString());
273 LPCOLESTR name = nameCopy.toUTF16();
274 DISPID id = 0;
275 if (source->GetIDsOfNames (IID_NULL, (LPOLESTR*) &name, 1, 0, &id) == S_OK)
277 VARIANT param;
278 zerostruct (param);
279 juceVarToVariant (newValue, param);
281 DISPPARAMS dispParams;
282 zerostruct (dispParams);
283 dispParams.cArgs = 1;
284 dispParams.rgvarg = &param;
285 EXCEPINFO excepInfo;
286 zerostruct (excepInfo);
288 VARIANT result;
289 zerostruct (result);
290 UINT argError = 0;
292 if (source->Invoke (id, IID_NULL, 0, DISPATCH_PROPERTYPUT,
293 &dispParams, &result, &excepInfo, &argError) == S_OK)
295 VariantClear (&result);
298 VariantClear (&param);
302 void removeProperty (const Identifier& propertyName)
304 setProperty (propertyName, var::null);
307 bool hasMethod (const Identifier& methodName) const
309 const String nameCopy (methodName.toString());
310 LPCOLESTR name = nameCopy.toUTF16();
311 DISPID id = 0;
312 return source->GetIDsOfNames (IID_NULL, (LPOLESTR*) &name, 1, 0, &id) == S_OK;
315 var invokeMethod (const Identifier& methodName, const var* parameters, int numParameters)
317 var returnValue;
318 const String nameCopy (methodName.toString());
319 LPCOLESTR name = nameCopy.toUTF16();
320 DISPID id = 0;
321 if (source->GetIDsOfNames (IID_NULL, (LPOLESTR*) &name, 1, 0, &id) == S_OK)
323 HeapBlock <VARIANT> params;
324 params.calloc (numParameters + 1);
326 for (int i = 0; i < numParameters; ++i)
327 juceVarToVariant (parameters[(numParameters - 1) - i], params[i]);
329 DISPPARAMS dispParams;
330 zerostruct (dispParams);
331 dispParams.cArgs = numParameters;
332 dispParams.rgvarg = params;
334 EXCEPINFO excepInfo;
335 zerostruct (excepInfo);
337 VARIANT result;
338 zerostruct (result);
339 UINT argError = 0;
341 if (source->Invoke (id, IID_NULL, 0, DISPATCH_METHOD,
342 &dispParams, &result, &excepInfo, &argError) == S_OK)
344 returnValue = variantTojuceVar (result);
345 VariantClear (&result);
349 return returnValue;
354 //==============================================================================
355 void juceVarToVariant (const var& v, VARIANT& dest)
357 if (v.isVoid())
359 dest.vt = VT_EMPTY;
361 else if (v.isInt())
363 dest.vt = VT_INT;
364 dest.intVal = (int) v;
366 else if (v.isBool())
368 dest.vt = VT_BOOL;
369 dest.boolVal = (int) v;
371 else if (v.isDouble())
373 dest.vt = VT_R8;
374 dest.dblVal = (double) v;
376 else if (v.isString())
378 dest.vt = VT_BSTR;
379 dest.bstrVal = SysAllocString (v.toString().toUTF16());
381 else if (v.getDynamicObject() != nullptr)
383 dest.vt = VT_DISPATCH;
384 dest.pdispVal = new IDispatchWrappingDynamicObject (v);
386 else if (v.isMethod())
388 dest.vt = VT_EMPTY;
392 const var variantTojuceVar (const VARIANT& v)
394 if ((v.vt & VT_ARRAY) != 0)
396 //xxx
398 else
400 switch (v.vt & ~VT_BYREF)
402 case VT_VOID:
403 case VT_EMPTY: return var::null;
404 case VT_I1: return var ((int) v.cVal);
405 case VT_I2: return var ((int) v.iVal);
406 case VT_I4: return var ((int) v.lVal);
407 case VT_I8: return var (String (v.llVal));
408 case VT_UI1: return var ((int) v.bVal);
409 case VT_UI2: return var ((int) v.uiVal);
410 case VT_UI4: return var ((int) v.ulVal);
411 case VT_UI8: return var (String (v.ullVal));
412 case VT_INT: return var ((int) v.intVal);
413 case VT_UINT: return var ((int) v.uintVal);
414 case VT_R4: return var ((double) v.fltVal);
415 case VT_R8: return var ((double) v.dblVal);
416 case VT_BSTR: return var (String (v.bstrVal));
417 case VT_BOOL: return var (v.boolVal ? true : false);
418 case VT_DISPATCH: return var (new DynamicObjectWrappingIDispatch (v.pdispVal));
419 default:
420 break;
424 return var::null;
427 //==============================================================================
428 // This acts as the embedded HWND
429 class AXBrowserPluginHolderComponent : public Component
431 public:
432 //==============================================================================
433 AXBrowserPluginHolderComponent()
434 : parentHWND (0),
435 browser (nullptr)
437 setOpaque (true);
438 setWantsKeyboardFocus (false);
440 addAndMakeVisible (child = createBrowserPlugin());
441 jassert (child != nullptr); // You have to create one of these!
444 ~AXBrowserPluginHolderComponent()
446 setWindow (nullptr);
447 child = nullptr;
450 //==============================================================================
451 void paint (Graphics& g)
453 if (child == nullptr || ! child->isOpaque())
454 g.fillAll (Colours::white);
457 void resized()
459 if (child != nullptr)
460 child->setBounds (0, 0, getWidth(), getHeight());
463 const var getObject() { return child->getJavascriptObject(); }
465 void setWindow (IOleInPlaceSite* site)
467 if (browser != nullptr)
469 browser->Release();
470 browser = nullptr;
473 HWND newHWND = 0;
475 if (site != nullptr)
477 site->GetWindow (&newHWND);
479 IServiceProvider* sp = nullptr;
480 site->QueryInterface (IID_IServiceProvider, (void**) &sp);
482 if (sp != nullptr)
484 sp->QueryService (IID_IWebBrowserApp, IID_IWebBrowser2, (void**) &browser);
485 sp->Release();
489 if (parentHWND != newHWND)
491 removeFromDesktop();
492 setVisible (false);
494 parentHWND = newHWND;
496 if (parentHWND != 0)
498 addToDesktop (0);
500 HWND ourHWND = (HWND) getWindowHandle();
501 SetParent (ourHWND, parentHWND);
502 DWORD val = GetWindowLong (ourHWND, GWL_STYLE);
503 val = (val & ~WS_POPUP) | WS_CHILD;
504 SetWindowLong (ourHWND, GWL_STYLE, val);
506 setVisible (true);
510 if (site != nullptr)
511 site->OnInPlaceActivate();
514 const String getBrowserURL() const
516 if (browser == nullptr)
517 return String::empty;
519 BSTR url = nullptr;
520 browser->get_LocationURL (&url);
521 return URL::removeEscapeChars (url);
524 private:
525 //==============================================================================
526 ScopedPointer<BrowserPluginComponent> child;
527 HWND parentHWND;
528 IWebBrowser2* browser;
531 //==============================================================================
532 extern String browserVersionDesc;
534 static const String getExePath()
536 TCHAR moduleFile [2048] = { 0 };
537 GetModuleFileName (0, moduleFile, 2048);
538 return moduleFile;
541 static const String getExeVersion (const String& exeFileName, const String& fieldName)
543 String resultString;
544 DWORD pointlessWin32Variable;
545 DWORD size = GetFileVersionInfoSize (exeFileName.toUTF16(), &pointlessWin32Variable);
547 if (size > 0)
549 HeapBlock <char> exeInfo;
550 exeInfo.calloc (size);
552 if (GetFileVersionInfo (exeFileName.toUTF16(), 0, size, exeInfo))
554 TCHAR* result = nullptr;
555 unsigned int resultLen = 0;
557 // try the 1200 codepage (Unicode)
558 String queryStr ("\\StringFileInfo\\040904B0\\" + fieldName);
560 if (! VerQueryValue (exeInfo, (LPTSTR) queryStr.toUTF16().getAddress(), (void**) &result, &resultLen))
562 // try the 1252 codepage (Windows Multilingual)
563 queryStr = "\\StringFileInfo\\040904E4\\" + fieldName;
564 VerQueryValue (exeInfo, (LPTSTR) queryStr.toUTF16().getAddress(), (void**) &result, &resultLen);
567 resultString = String (result, resultLen);
571 return resultString;
574 static int numActivePlugins = 0;
576 class JuceActiveXObject : public IUnknown,
577 public IDispatch,
578 public IObjectWithSite,
579 public IObjectSafety,
580 public IOleInPlaceObject
582 public:
583 JuceActiveXObject()
584 : site (nullptr), refCount (0)
586 log ("JuceActiveXObject");
589 ~JuceActiveXObject()
591 log ("~JuceActiveXObject");
592 holderComp = nullptr;
595 HRESULT __stdcall QueryInterface (REFIID id, void __RPC_FAR* __RPC_FAR* result)
597 if (id == IID_IUnknown) { AddRef(); *result = (IUnknown*) this; return S_OK; }
598 else if (id == IID_IDispatch) { AddRef(); *result = (IDispatch*) this; return S_OK; }
599 else if (id == IID_IObjectWithSite) { AddRef(); *result = (IObjectWithSite*) this; return S_OK; }
600 else if (id == IID_IObjectSafety) { AddRef(); *result = (IObjectSafety*) this; return S_OK; }
601 else if (id == IID_IOleInPlaceObject) { AddRef(); *result = (IOleInPlaceObject*) this; return S_OK; }
602 else if (id == IID_IOleWindow) { AddRef(); *result = (IOleWindow*) (IOleInPlaceObject*) this; return S_OK; }
604 *result = 0;
605 return E_NOINTERFACE;
608 ULONG __stdcall AddRef() { return ++refCount; }
609 ULONG __stdcall Release() { const int r = --refCount; if (r == 0) delete this; return r; }
611 HRESULT __stdcall GetTypeInfoCount (UINT* pctinfo) { return E_NOTIMPL; }
612 HRESULT __stdcall GetTypeInfo (UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) { return E_NOTIMPL; }
614 HRESULT __stdcall GetIDsOfNames (REFIID riid, LPOLESTR* rgszNames, UINT cNames,
615 LCID lcid, DISPID* rgDispId)
617 return iDispatchHelper.doGetIDsOfNames (rgszNames, cNames, rgDispId);
620 HRESULT __stdcall Invoke (DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
621 DISPPARAMS* pDispParams, VARIANT* pVarResult,
622 EXCEPINFO* pExcepInfo, UINT* puArgErr)
624 if (holderComp == nullptr)
625 return DISP_E_MEMBERNOTFOUND;
627 return iDispatchHelper.doInvoke (holderComp->getObject(),
628 dispIdMember, riid, lcid, wFlags, pDispParams,
629 pVarResult, pExcepInfo, puArgErr);
632 HRESULT __stdcall SetSite (IUnknown* newSite)
634 if (newSite != site)
636 if (site != nullptr)
637 site->Release();
639 site = newSite;
641 if (site != nullptr)
643 site->AddRef();
645 IOleInPlaceSite* inPlaceSite = nullptr;
646 site->QueryInterface (IID_IOleInPlaceSite, (void**) &inPlaceSite);
648 if (inPlaceSite != nullptr)
650 createHolderComp();
652 holderComp->setWindow (inPlaceSite);
653 inPlaceSite->Release();
655 else
657 deleteHolderComp();
660 else
662 deleteHolderComp();
666 return S_OK;
669 void createHolderComp()
671 if (holderComp == nullptr)
673 if (numActivePlugins++ == 0)
675 log ("initialiseJuce_GUI()");
676 initialiseJuce_GUI();
678 browserVersionDesc = "Internet Explorer " + getExeVersion (getExePath(), "FileVersion");
681 holderComp = new AXBrowserPluginHolderComponent();
685 void deleteHolderComp()
687 if (holderComp != nullptr)
689 holderComp = nullptr;
691 if (--numActivePlugins == 0)
693 log ("shutdownJuce_GUI()");
694 shutdownJuce_GUI();
699 HRESULT __stdcall GetSite (REFIID riid, void **ppvSite)
701 *ppvSite = site;
702 return S_OK;
705 //==============================================================================
706 HRESULT __stdcall SetObjectRects (LPCRECT r, LPCRECT c)
708 if (holderComp != nullptr)
709 holderComp->setBounds (r->left, r->top, r->right - r->left, r->bottom - r->top);
711 return S_OK;
714 HRESULT __stdcall GetWindow (HWND* phwnd)
716 if (holderComp == nullptr)
717 return E_NOTIMPL;
719 *phwnd = (HWND) holderComp->getWindowHandle();
720 return S_OK;
723 //==============================================================================
724 HRESULT __stdcall ContextSensitiveHelp (BOOL fEnterMode) { return E_NOTIMPL; }
725 HRESULT __stdcall InPlaceDeactivate() { return E_NOTIMPL; }
726 HRESULT __stdcall UIDeactivate() { return E_NOTIMPL; }
727 HRESULT __stdcall ReactivateAndUndo() { return E_NOTIMPL; }
729 //==============================================================================
730 HRESULT __stdcall GetInterfaceSafetyOptions (REFIID riid, DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions)
732 *pdwSupportedOptions = *pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA;
733 return S_OK;
736 HRESULT __stdcall SetInterfaceSafetyOptions (REFIID, DWORD, DWORD) { return S_OK; }
738 private:
739 IUnknown* site;
740 int refCount;
741 ScopedPointer<AXBrowserPluginHolderComponent> holderComp;
742 IDispatchHelper iDispatchHelper;
744 JuceActiveXObject (const JuceActiveXObject&);
745 JuceActiveXObject& operator= (const JuceActiveXObject&);
748 //==============================================================================
749 class JuceActiveXObjectFactory : public IUnknown,
750 public IClassFactory
752 public:
753 JuceActiveXObjectFactory() : refCount (0) {}
754 ~JuceActiveXObjectFactory() {}
756 HRESULT __stdcall QueryInterface (REFIID id, void __RPC_FAR* __RPC_FAR* result)
758 if (id == IID_IUnknown) { AddRef(); *result = (IUnknown*) this; return S_OK; }
759 else if (id == IID_IClassFactory) { AddRef(); *result = (IClassFactory*) this; return S_OK; }
761 *result = 0;
762 return E_NOINTERFACE;
765 ULONG __stdcall AddRef() { return ++refCount; }
766 ULONG __stdcall Release() { const int r = --refCount; if (r == 0) delete this; return r; }
768 HRESULT __stdcall CreateInstance (IUnknown* pUnkOuter, REFIID riid, void** ppvObject)
770 *ppvObject = nullptr;
772 if (pUnkOuter != nullptr && riid != IID_IUnknown)
773 return CLASS_E_NOAGGREGATION;
775 JuceActiveXObject* ax = new JuceActiveXObject();
776 return ax->QueryInterface (riid, ppvObject);
779 HRESULT __stdcall LockServer (BOOL /*fLock*/) { return S_OK; }
781 private:
782 int refCount;
784 JuceActiveXObjectFactory (const JuceActiveXObjectFactory&);
785 JuceActiveXObjectFactory& operator= (const JuceActiveXObjectFactory&);
788 //==============================================================================
789 const String getActiveXBrowserURL (const BrowserPluginComponent* comp)
791 AXBrowserPluginHolderComponent* const ax = dynamic_cast <AXBrowserPluginHolderComponent*> (comp->getParentComponent());
792 return ax != nullptr ? ax->getBrowserURL() : String::empty;
795 //==============================================================================
796 extern "C" BOOL WINAPI DllMain (HANDLE instance, DWORD reason, LPVOID)
798 #pragma EXPORTED_FUNCTION
800 switch (reason)
802 case DLL_PROCESS_ATTACH:
803 log ("DLL_PROCESS_ATTACH");
804 PlatformUtilities::setCurrentModuleInstanceHandle (instance);
805 break;
807 case DLL_PROCESS_DETACH:
808 log ("DLL_PROCESS_DETACH");
809 browserVersionDesc = String::empty;
811 // IE has a tendency to leak our objects, so although none of this should be
812 // necessary, it's best to make sure..
813 jassert (numActivePlugins == 0);
814 shutdownJuce_GUI();
815 break;
817 default:
818 break;
821 return TRUE;
824 static const String CLSIDToJuceString (REFCLSID clsid)
826 LPWSTR s = nullptr;
827 StringFromIID (clsid, &s);
829 if (s == nullptr)
830 return String::empty;
832 const String result (s);
833 LPMALLOC malloc;
834 CoGetMalloc (1, &malloc);
835 if (malloc != nullptr)
837 malloc->Free (s);
838 malloc->Release();
841 return result.removeCharacters ("{}").trim();
844 STDAPI DllGetClassObject (REFCLSID rclsid, REFIID riid, LPVOID* ppv)
846 #pragma EXPORTED_FUNCTION
848 *ppv = nullptr;
850 if (CLSIDToJuceString (rclsid).equalsIgnoreCase (String (JuceBrowserPlugin_ActiveXCLSID)))
852 JuceActiveXObjectFactory* afx = new JuceActiveXObjectFactory();
853 if (afx->QueryInterface (riid, ppv) == S_OK)
854 return S_OK;
856 delete afx;
859 return CLASS_E_CLASSNOTAVAILABLE;
862 STDAPI DllCanUnloadNow()
864 #pragma EXPORTED_FUNCTION
865 return S_OK;
868 //==============================================================================
869 static const String makeLegalRegistryName (const String& s)
871 return s.retainCharacters ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.");
874 static HRESULT doRegistration (const bool unregister)
876 const String company (makeLegalRegistryName (JuceBrowserPlugin_Company));
877 const String plugin (makeLegalRegistryName (JuceBrowserPlugin_Name));
878 const String clsID ("{" + String (JuceBrowserPlugin_ActiveXCLSID).toUpperCase() + "}");
879 const String root ("HKEY_CLASSES_ROOT\\");
880 const String companyDotPlugin (company + "." + plugin);
881 const String companyDotPluginCur (companyDotPlugin + ".1");
882 const String clsIDRoot (root + "CLSID\\" + clsID + "\\");
883 const String dllPath (File::getSpecialLocation (File::currentApplicationFile).getFullPathName());
885 StringPairArray settings;
886 settings.set (root + companyDotPluginCur + "\\", JuceBrowserPlugin_Name);
887 settings.set (root + companyDotPluginCur + "\\CLSID\\", clsID);
888 settings.set (root + companyDotPlugin + "\\", JuceBrowserPlugin_Name);
889 settings.set (root + companyDotPlugin + "\\CLSID\\", clsID);
890 settings.set (root + companyDotPlugin + "\\CurVer\\", companyDotPluginCur);
891 settings.set (clsIDRoot, JuceBrowserPlugin_Name);
892 settings.set (clsIDRoot + "Implemented Categories\\{7DD95801-9882-11CF-9FA9-00AA006C42C4}\\", String::empty);
893 settings.set (clsIDRoot + "Implemented Categories\\{7DD95802-9882-11CF-9FA9-00AA006C42C4}\\", String::empty);
894 settings.set (clsIDRoot + "ProgID\\", companyDotPluginCur);
895 settings.set (clsIDRoot + "VersionIndependentProgID\\", companyDotPlugin);
896 settings.set (clsIDRoot + "Programmable\\", String::empty);
897 settings.set (clsIDRoot + "InProcServer32\\", dllPath);
898 settings.set (clsIDRoot + "InProcServer32\\ThreadingModel", "Apartment");
899 settings.set (clsIDRoot + "Control\\", String::empty);
900 settings.set (clsIDRoot + "Insertable\\", String::empty);
901 settings.set (clsIDRoot + "ToolboxBitmap32\\", dllPath + ", 101");
902 settings.set (clsIDRoot + "TypeLib\\", "");
903 settings.set (clsIDRoot + "Version\\", JuceBrowserPlugin_Version);
905 if (unregister)
907 for (int i = 0; i < settings.getAllKeys().size(); ++i)
908 PlatformUtilities::deleteRegistryValue (settings.getAllKeys()[i]);
910 PlatformUtilities::deleteRegistryKey (root + companyDotPluginCur);
911 PlatformUtilities::deleteRegistryKey (root + companyDotPlugin);
912 PlatformUtilities::deleteRegistryKey (clsIDRoot);
914 if (PlatformUtilities::registryValueExists (clsIDRoot + "InProcServer32"))
915 return SELFREG_E_CLASS;
917 else
919 PlatformUtilities::deleteRegistryKey (clsIDRoot);
921 for (int i = 0; i < settings.getAllKeys().size(); ++i)
922 PlatformUtilities::setRegistryValue (settings.getAllKeys()[i],
923 settings [settings.getAllKeys()[i]]);
925 // check whether the registration actually worked - if not, we probably don't have
926 // enough privileges to write to the registry..
927 if (PlatformUtilities::getRegistryValue (clsIDRoot + "InProcServer32\\") != dllPath)
928 return SELFREG_E_CLASS;
931 return S_OK;
934 STDAPI DllRegisterServer()
936 #pragma EXPORTED_FUNCTION
937 return doRegistration (false);
940 STDAPI DllUnregisterServer()
942 #pragma EXPORTED_FUNCTION
943 return doRegistration (true);
946 #endif